package com.ims.shiro;


import com.ims.entity.system.User;
import com.ims.service.UserService;
import com.ims.util.Const;
import com.ims.util.LoggerUtils;
import com.ims.util.PageData;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

/**
 * 自定义Realm,进行数据源配置
 * 
 * @author lur

 * @version 1.0v
 */
public class MyRealm extends AuthorizingRealm {

    @Resource
    UserService userService;
    @Resource
    ShiroSessionService sessionService;


	/**
	 * 只有需要验证权限时才会调用, 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.在配有缓存的情况下，只加载一次.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		System.out.println("========2");

		return null;
	}

	/**
	 * 认证回调函数,登录时调用
	 * 首先根据传入的用户名获取User信息；然后如果user为空，那么抛出没找到帐号异常UnknownAccountException；
	 * 如果user找到但锁定了抛出锁定异常LockedAccountException；最后生成AuthenticationInfo信息，
	 * 交给间接父类AuthenticatingRealm使用CredentialsMatcher进行判断密码是否匹配，
	 * 如果不匹配将抛出密码错误异常IncorrectCredentialsException；
	 * 另外如果密码重试此处太多将抛出超出重试次数异常ExcessiveAttemptsException；
	 * 在组装SimpleAuthenticationInfo信息时， 需要传入：身份信息（用户名）、凭据（密文密码）、盐（username+salt），
	 * CredentialsMatcher使用盐加密传入的明文密码和此处的密文密码进行匹配。
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

             UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
             PageData pd = new PageData();
             pd.put("USERNAME", token.getUsername());


            LoggerUtils.logInfo("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));


          if(!StringUtils.isEmpty(token.getUsername()))
          {
              try {
                  pd = userService.findByUId(pd);
                  if (pd != null)
                  {
                      User user = new User();
                      user.setUSER_ID(pd.getString("USER_ID"));
                      user.setUSERNAME(pd.getString("USERNAME"));
                      this.setSession(Const.SESSION_USER,user);
                      // 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以自定义实现
                  }else{
                      throw new AccountException("帐号或密码不正确！");
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }



          }

        return new SimpleAuthenticationInfo(pd.get("USERNAME"), pd.getString("PASSWORD"), this.getName());





    }

    /**
     * 将一些数据放到ShiroSession中,以便于其它地方使用
     * @see
     */
    private void setSession(Object key, Object value) throws Exception {

        //ShiroSessionService session = new ShiroSessionService();
        if(null != sessionService){
            sessionService.setAttribute(key, value);
        }

    }
}